home *** CD-ROM | disk | FTP | other *** search
- /*---------------------------------------------------------------------------
-
- unix.c
-
- Unix-specific routines for use with Info-ZIP's UnZip 5.1 and later.
-
- ---------------------------------------------------------------------------*/
-
-
- #include "unzip.h"
-
-
- /**********************/
- /* Function mapattr() */
- /**********************/
-
- int mapattr()
- {
- ulg tmp = crec.external_file_attributes;
-
- switch (pInfo->hostnum) {
- case UNIX_:
- case VMS_:
- pInfo->file_attr = (unsigned)(tmp >> 16);
- return 0;
- case AMIGA_:
- tmp = (unsigned)(tmp>>17 & 7); /* Amiga RWE bits */
- pInfo->file_attr = (unsigned)(tmp<<6 | tmp<<3 | tmp);
- break;
- /* all remaining cases: expand MSDOS read-only bit into write perms */
- case FS_FAT_:
- case FS_HPFS_:
- case FS_NTFS_:
- case MAC_:
- case ATARI_: /* (used to set = 0666) */
- case TOPS20_:
- default:
- tmp = !(tmp & 1) << 1; /* read-only bit --> write perms bits */
- pInfo->file_attr = (unsigned)(0444 | tmp<<6 | tmp<<3 | tmp);
- break;
- } /* end switch (host-OS-created-by) */
-
- /* for originating systems with no concept of "group," "other," "system": */
- umask( (int)(tmp=umask(0)) ); /* apply mask to expanded r/w(/x) perms */
- pInfo->file_attr &= ~tmp;
-
- return 0;
-
- } /* end function mapattr() */
-
-
-
-
-
- /**************************************/
- /* Function set_file_time_and_close() */
- /**************************************/
-
- void set_file_time_and_close()
- {
- static short yday[]={0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
- long m_time;
- int yr, mo, dy, hh, mm, ss, leap, days=0;
- struct utimbuf tp;
- # define YRBASE 1970
- #ifndef __386BSD__
- #ifdef BSD
- static struct timeb tbp;
- #else /* !BSD */
- extern long timezone;
- #endif /* ?BSD */
- #endif /* !__386BSD__ */
-
-
- /*---------------------------------------------------------------------------
- If symbolic links are supported, allocate a storage area, put the uncom-
- pressed "data" in it, and create the link. Since we know it's a symbolic
- link to start with, we shouldn't have to worry about overflowing unsigned
- ints with unsigned longs.
- ---------------------------------------------------------------------------*/
-
- #ifdef SYMLINKS
- if (symlnk) {
- unsigned ucsize = (unsigned)lrec.ucsize;
- char *linktarget = (char *)malloc((unsigned)lrec.ucsize+1);
-
- close(outfd); /* close "data" file... */
- outfd = open(filename, O_RDONLY); /* ...and reopen for reading */
- if (!linktarget || (read(outfd, linktarget, ucsize) != ucsize)) {
- fprintf(stderr, "\nwarning: symbolic link (%s) failed\n",
- filename);
- if (linktarget)
- free(linktarget);
- close(outfd);
- return;
- }
- close(outfd); /* close "data" file for good... */
- unlink(filename); /* ...and delete it */
- linktarget[ucsize] = '\0';
- fprintf(stdout, "-> %s ", linktarget);
- if (symlink(linktarget, filename)) /* create the real link */
- perror("symlink error");
- free(linktarget);
- return; /* can't set time on symlinks */
- }
- #endif /* SYMLINKS */
-
- close(outfd);
- if (cflag) /* can't set time on stdout */
- return;
-
- /*---------------------------------------------------------------------------
- Convert from MSDOS-format local time and date to Unix-format 32-bit GMT
- time: adjust base year from 1980 to 1970, do usual conversions from
- yy/mm/dd hh:mm:ss to elapsed seconds, and account for timezone and day-
- light savings time differences.
- ---------------------------------------------------------------------------*/
-
- yr = ((lrec.last_mod_file_date >> 9) & 0x7f) + (1980 - YRBASE);
- mo = ((lrec.last_mod_file_date >> 5) & 0x0f) - 1;
- dy = (lrec.last_mod_file_date & 0x1f) - 1;
- hh = (lrec.last_mod_file_time >> 11) & 0x1f;
- mm = (lrec.last_mod_file_time >> 5) & 0x3f;
- ss = (lrec.last_mod_file_time & 0x1f) * 2;
-
- /* leap = # of leap yrs from YRBASE up to but not including current year */
- leap = ((yr + YRBASE - 1) / 4); /* leap year base factor */
-
- /* how many days from YRBASE to this year? (& add expired days this year) */
- days = (yr * 365) + (leap - 492) + yday[mo];
-
- /* if year is a leap year and month is after February, add another day */
- if ((mo > 1) && ((yr+YRBASE)%4 == 0) && ((yr+YRBASE) != 2100))
- ++days; /* OK through 2199 */
-
- /* convert date & time to seconds relative to 00:00:00, 01/01/YRBASE */
- m_time = ((days + dy) * 86400) + (hh * 3600) + (mm * 60) + ss;
-
- /* adjust for local timezone */
- #ifdef BSD
- #ifdef __386BSD__
- m_time -= localtime(&m_time)->tm_gmtoff; /* seconds EAST of GMT: subtr. */
- #else /* !__386BSD__ */
- ftime(&tbp); /* get `timezone' */
- m_time += tbp.timezone * 60L; /* seconds WEST of GMT: add */
- #endif /* ?__386BSD__ */
- #else /* !BSD */
- tzset(); /* get `timezone' */
- m_time += timezone; /* seconds WEST of GMT: add */
- #endif /* ?BSD */
-
- /* adjust for daylight savings time (or local equivalent) */
- #ifndef __386BSD__ /* (DST already added to tm_gmtoff, so skip tm_isdst) */
- if (localtime(&m_time)->tm_isdst)
- m_time -= 60L * 60L; /* adjust for daylight savings time */
- #endif
-
- /* set the file's access and modification times */
- tp.actime = tp.modtime = m_time;
- if (utime(filename, &tp))
- fprintf(stderr, "warning: can't set the time for %s\n", filename);
-
- } /* end function set_file_time_and_close() */
-